package org.opens.mybatisplus.service.impl;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.commons.lang3.StringUtils;
import org.opens.mybatisplus.dao.JpaUserDoDao;
import org.opens.mybatisplus.pojo.JpaUserDo;
import org.opens.mybatisplus.service.JpaUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;

@Service(value = "userService")
public class JpaUserServiceImpl implements JpaUserService {

    @Autowired
    private JpaUserDoDao jpaUserDoDao;

    @Transactional(rollbackFor = RuntimeException.class)
    @Override
    public boolean removeById(int id) {
        int affectedRows = jpaUserDoDao.deleteById(id);
        if(id == 65538) {
            jpaUserDoDao.deleteById(8);
            double a = 1 / 0;
        }
        return affectedRows == 1;
    }

    /**
     * 功能:
     *      -简介
     *          通过wrapper条件构造器构造出复杂条件-> or的嵌套.
     *      -执行的sql
     *          SELECT id,old,name FROM jpa_user WHERE (id < ? AND name LIKE ? OR ( (old < ? AND id <> ?) ))
     */
    @Override
    public List<JpaUserDo> listByIdAndNameOrOld(int id, String name, int old) {
        QueryWrapper<JpaUserDo> wrapper = new QueryWrapper<>();
        if(id > 0) {
            wrapper.lt("id", id);
        }
        if(StrUtil.isNotBlank(name)) {
            wrapper.like("name", name);
        }
        if(old > 0) {
            wrapper.or(i -> i.lt("old", old).ne("id", 3));
        }
        //指定排序
        wrapper.orderByAsc("id", "name", "old");
        return jpaUserDoDao.selectList(wrapper);
    }

    /**
     * 功能:
     *      -简介
     *          使用Mybatis plus的Page对象和Ipage对象来实现自定义方法的快速分页查询.
     *      -执行的sql
     *          --执行的sql1
     *              SELECT COUNT(1) FROM jpa_user WHERE (1 = 1)
     *          --执行的sql2
     *              select id, name, old from jpa_user WHERE ( 1 = 1 ) LIMIT ?,?
     * 说明:
     *      1. sql1并不是自己实现的, 而是mybatis plus帮助我们实现的, 它会自动检测传入的条件, 统计所有数据的行数.
     *      2. sql2在自定义mapper.xml文件中并没有limit语句, 而是mybatis plus的sql拦截器自动帮助我们实现的.
     * 优点:
     *      1. 不需要写两套sql了, 只需要写获取数据就可以了, mybatis plus自动帮我们获取相应条件下的数据总行数.
     * 引申:
     *      1. 如果只是查询数据并不需要统计所有行数, 只需要一个改动即可:
     *          - Page<JpaUserDo> page = new Page<>(pageNumber, pageSize, false);
     *              1. 在page对象的构造器中传入额外参数false, 就会使mybaits plus不去统计所有行数, 只会返回所有数据.
     */
    @Override
    public IPage<JpaUserDo> selectByPage(int pageNumber, int pageSize, int id, String name, int old) {
        Page<JpaUserDo> page = new Page<>(pageNumber, pageSize);
        return jpaUserDoDao.mySelectPage(page, id, name, old);
    }

    /**
     * 说明:
     *      -注意
     *          mybatis plus的这个构建条件嵌套有一个坑就是: 即使知道了要使用lambda来构建条件嵌套, 但是有时
     *          还是会习惯性的直接在一个条件之后接着写lambda嵌套条件, 但是此时就会使最终的sql拼接一个(null).
     *          --说明
     *              1. 可以能原码的bug吧.
     *              2. 错误示例请看注释.
     * @param pageNumber
     * @param pageSize
     * @param ids
     * @param name
     * @param old
     * @return
     */
    @Override
    public IPage<JpaUserDo> useQueryWrapperSelectPage(int pageNumber, int pageSize, int[] ids, String name, int old) {
        Page<JpaUserDo> page = new Page<>(pageNumber, pageSize);
        QueryWrapper<JpaUserDo> wrapper = new QueryWrapper<>();

        if(old > 0) {
            wrapper.lt("old", old);
            /**
             * 错误实例:
             *     wrapper.lt("old", old).and(wrapperTemp2 -> {     //错误就在这里, 不能接着写, 只能重新开一行写.
             *         if(ids.length != 0 && StringUtils.isNotBlank(name)) {
             *             List<Integer> idList = new ArrayList<>();
             *             for(int id : ids) {
             *                 idList.add(id);
             *             }
             *             wrapper.and(wrapperTemp2 -> wrapperTemp2.in("id", idList).or().like("name", name));
             *         } else if(ids.length != 0) {
             *             List<Integer> idList = new ArrayList<>();
             *             for(int id : ids) {
             *                 idList.add(id);
             *             }
             *             wrapper.and(wrapperTemp2 -> wrapperTemp2.in("id", idList));
             *         } else if(StringUtils.isNotBlank(name)) {
             *             wrapper.and(wrapperTemp2 -> wrapperTemp2.like("name", name));
             *         }
             *     });
             */
        }
        if(ids.length != 0 && StringUtils.isNotBlank(name)) {
            List<Integer> idList = new ArrayList<>();
            for(int id : ids) {
                idList.add(id);
            }
            wrapper.and(wrapperTemp2 -> wrapperTemp2.in("id", idList).or().like("name", name));
        } else if(ids.length != 0) {
            List<Integer> idList = new ArrayList<>();
            for(int id : ids) {
                idList.add(id);
            }
            wrapper.and(wrapperTemp2 -> wrapperTemp2.in("id", idList));
        } else if(StringUtils.isNotBlank(name)) {
            wrapper.and(wrapperTemp2 -> wrapperTemp2.like("name", name));
        }

        return jpaUserDoDao.selectPage(page, wrapper);
    }

    @Override
    public IPage<JpaUserDo> selectByNameFromLambda(int pageNumber, int pageSize, String name) {
        Page<JpaUserDo> page = new Page<>(pageNumber, pageSize);
        if(StringUtils.isBlank(name)) {
            return null;
        }
        QueryWrapper<JpaUserDo> wrapper = new QueryWrapper<>();
        wrapper.lambda().like(JpaUserDo::getName, name);
        return jpaUserDoDao.selectPage(page, wrapper);
    }

}
